/*
 * This file is part of LangMan.
 *
 * LangMan is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * LangMan is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with LangMan.  If not, see <http://www.gnu.org/licenses/>.
 */

package langman.gui.tree;

import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.ObservableList;
import javafx.collections.ObservableMap;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import langman.Utils;
import langman.business.actions.common.ActionTypes;
import langman.business.actions.defaults.AddEnabled;
import langman.business.actions.defaults.EditEnabled;
import langman.business.actions.defaults.RemoveEnabled;
import langman.business.data.model.Category;
import langman.business.data.model.Key;
import langman.util.doping.Bean;
import langman.util.doping.Context;
import langman.util.doping.Inject;

import java.text.MessageFormat;
import java.text.NumberFormat;

@SuppressWarnings("rawtypes")
@Bean
public class CategoryItem extends TreeItem implements DecoratingTreeItem, SelectionAwareTreeItem, InvalidationListener, AddEnabled, EditEnabled, RemoveEnabled, FilterableTreeItem {

    private final Context context;

    private Category category;

    private final StringProperty text = new SimpleStringProperty();
    private final StringProperty style = new SimpleStringProperty();

    @Inject
    public CategoryItem(Context context) {
        this.context = context;
    }

    public void setCategory(Category category) {
        setValue(category);

        this.category = category;

        category.getKeysUnmodifiable().addListener((Observable observable) -> updateChildren());

        updateChildren();
        category.addListener(this);
        updateText();
    }

    private void updateChildren() {
        ObservableMap<String, Key> keyMap = getCategory().getKeysUnmodifiable();

        ObservableList children = getChildren();
        children.clear();
        for (Key key : keyMap.values()) {
            KeyItem keyItem = context.getBean(KeyItem.class);
            keyItem.setKey(key);
            children.add(keyItem);
        }
    }

    @Override
    public void decorate(TreeCell cell) {
        cell.textProperty().bind(text);
        cell.styleProperty().bind(style);
    }

    @Override
    public void selected() {

    }

    public Category getCategory() {
        return category;
    }

    @Override
    public void invalidated(Observable observable) {
        updateText();
    }

    private void updateText() {
        double completeness = category.getCompleteness();
        NumberFormat numberFormat = NumberFormat.getPercentInstance();
        text.set(MessageFormat.format("{0} ({1})", category.getName(), numberFormat.format(completeness)));

        String colorKey = Utils.getColorForCompleteness(completeness);
        style.set("-fx-background-color: " + colorKey + ";");
    }


    @Override
    public ActionTypes getAddAction() {
        return ActionTypes.AddKey;
    }

    @Override
    public ActionTypes getEditAction() {
        return ActionTypes.EditCategory;
    }

    @Override
    public ActionTypes getRemoveAction() {
        return ActionTypes.RemoveCategory;
    }

    @Override
    public boolean filter(String filterString) {
        ObservableMap<String, Key> keyMap = getCategory().getKeysUnmodifiable();

        ObservableList children = getChildren();
        children.clear();
        for (Key key : keyMap.values()) {
            KeyItem keyItem = context.getBean(KeyItem.class);
            keyItem.setKey(key);
            if (keyItem.filter(filterString)) {
                children.add(keyItem);
            }
        }

        return !children.isEmpty();
    }
}
